Go进阶(3): 函数+闭包+defer | 您所在的位置:网站首页 › 闭包 golang › Go进阶(3): 函数+闭包+defer |
1. 函数是一种数据类型
函数参数的传递方式有值传递和引用传递(指针/slicer/map/channel/interface)两种;不管哪一种,传递的都是值或者地址的副本;一般来说,地址传递的效率更高,因为数据量小,而值传递随着数据量的增加而效率降低(如结构体拷贝)。 示例: package main import ( "fmt" "reflect" ) func getSum(num1 int, num2 int) int { return num1+num2 } func main() { funcVar := getSum fmt.Println("the type of getSum :", reflect.TypeOf(getSum), " the type of funcVar :",reflect.TypeOf(funcVar)) res := getSum(10,20) fmt.Println("the result : ", res) }运行结果: the type of getSum : func(int, int) int the type of funcVar : func(int, int) int the result : 30 2. 函数可以作为形参示例: package main import "fmt" func getSum(num1 int, num2 int) int { return num1+num2 } func myFunc(funcVar func(int, int)int, num1 int, num2 int) int { return funcVar(num1, num2) } func main() { res := myFunc(getSum, 10,20) fmt.Println("the result : ", res) }运行结果: the result : 30 3. 支持自定义数据类型示例: package main import "fmt" type myFunType func(int, int)int // //定义函数类型的类型名 func getSum(num1 int, num2 int) int { return num1+num2 } func myFunc(funcVar myFunType, num1 int, num2 int) int { return funcVar(num1, num2) } func main() { type myInt int //定义基本数据类型的类型名 var num myInt = 40 fmt.Println("num : ", num) res := myFunc(getSum, 10 , 20) fmt.Println("res : ", res) }运行结果: num : 40 res : 30 4. 支持对函数返回值命名示例: package main import "fmt" func get_sum_sub(num1 int, num2 int) (sum int, sub int){ sum = num1 + num2 sub = num1 - num2 return } func main() { sum, sub := get_sum_sub(20, 10) fmt.Println("sum : ", sum, "sub : ", sub) }运行结果: sum : 30 sub : 10 5. 支持可变参数func(args... int) sum int{} // args是slice类型,可以通过args[index]访问各个值。 示例: package main import "fmt" func getSum(num1 int, args... int) int{ sum := num1 for i := 0; i init() -> main()init函数最大的作用是完成一些初始化的工作如果main.go和pkg.go, 执行流程 引用包的变量定义 -> 引用包的init() ->main()函数的变量定义 -> main()的init() package main import "fmt" var gVar = gTest() func gTest() string { fmt.Println("global variable:") return "global variable:" } func init() { fmt.Println("init function:") } func main() { fmt.Println("main function:") }运行结果: global variable: init function: main function: 7. 匿名函数Go也支持匿名函数,如果某个函数只希望使用一次,可以考虑匿名函数;当然,匿名函数也可以实现多次调用。 使用方式: 在定义匿名函数时直接就使用将匿名函数赋给一个变量(函数变量),再通过该变量调用匿名函数全局匿名函数可以在程序的任何地方进行调用 package main import "fmt" func main() { // case 1: getSum := func (num1 int, num2 int) int { return num1 + num2 }(10,20) fmt.Println("getSum = ", getSum) //case 2: getSub := func(num1 int, num2 int) int{ return num1-num2 } res := getSub(10,20) fmt.Println("getSub = ", res) }运行结果: getSum = 30 getSub = -10 8. 闭包闭包就是一个函数与其相关的引用环境的一个整体(实体) package main import "fmt" func addUpper() func(int)int { var n int = 10 //外部变量 return func (x int) int { //匿名函数引用外部变量 构成闭包 n += x return n } } func main() { myFun := addUpper() fmt.Println("1st close function", myFun(1)) fmt.Println("2nd close function", myFun(2)) fmt.Println("3rd close function", myFun(3)) }运行结果(每进行一次调用就进行累计,不会初始化): 1st close function 11 2nd close function 13 3rd close function 16 可以理解为:闭包是一个类,函数是操作,外部变量是字段 8. defer的使用技巧在函数中,我们经常需要创建资源(如,数据库连接 / 文件句柄 / 锁等),为了在函数执行完毕后,可以及时释放资源,Go框架设计了defer。 Note: 当go执行到一个defer时,不会立即执行defer后面的语句,而是将defer后面的语句压进栈中(可以理解为defer栈)当函数执行结束后,defer 语句出栈,遵循先入后出在defer将语句放入栈中时,也会将相关的值Copy,同时入栈defer最主要的价值在于,当函数执行完毕后,可以及时地释放函数创建的资源,如defer file.close() / defer connect.close()示例: package main import "fmt" func sum(num1 int, num2 int) int { defer fmt.Println("defer1 num1=", num1) //暂时不执行,压进defer栈中 defer fmt.Println("defer2 num2=", num2) res := num1 + num2 fmt.Println("resFun=", res) return res } func main() { res := sum(10,20) // 当函数执行完毕后,defer按照先进后出的方式出栈 fmt.Println("res=",res) }运行结果: resFun= 30 defer2 num2= 20 defer1 num1= 10 res= 30 |
CopyRight 2018-2019 实验室设备网 版权所有 |